package com.healthdata.service;

import com.healthdata.entity.NaiveBayesMissingValueFiller;
import org.springframework.stereotype.Service;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.*;

@Service
public class DataCleanService {

    /**
     * 基于目标列和依赖列进行数据缺失值填充
     *
     * @param data            原始数据（Map列表，键为列名，值为单元格数据）
     * @param targetColumn    需要填充缺失值的目标列名
     * @param dependentColumns 用于推断填充值的依赖列名列表
     * @return 填充后的完整数据
     */
    public List<Map<String, Object>> cleanMissingValues(
            List<Map<String, Object>> data,
            String targetColumn,
            List<String> dependentColumns) throws IOException {

        // 参数校验
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("数据不能为空");
        }
        if (targetColumn == null || targetColumn.trim().isEmpty()) {
            throw new IllegalArgumentException("targetColumn不能为空");
        }

        // 特殊处理自增ID列（不依赖算法，直接填充）
        if ("id".equalsIgnoreCase(targetColumn)) {
            return fillSequentialId(data);
        }

        // 确保目标列和依赖列存在
        Map<String, Object> firstRow = data.get(0);
        if (!firstRow.containsKey(targetColumn)) {
            throw new IllegalArgumentException("目标列不存在: " + targetColumn);
        }

        for (String column : dependentColumns) {
            if (!firstRow.containsKey(column)) {
                throw new IllegalArgumentException("依赖列不存在: " + column);
            }
        }

        // 创建算法配置文件（指定目标列和依赖列索引）
        Path configPath = createTempConfigFile(targetColumn, dependentColumns, data);

        // 转换数据格式为算法输入格式
        List<String> formattedData = formatDataForAlgorithm(data);

        // 执行贝叶斯算法填充缺失值
        NaiveBayesMissingValueFiller filler = new NaiveBayesMissingValueFiller();
        filler.init(configPath.toString());
        List<String> filledData = filler.fill(configPath.toString(), formattedData);

        // 转换回原始数据结构
        return parseFormattedData(filledData);
    }

    /**
     * 高级去重功能：基于查重列去重，并重新排序主键ID
     *
     * @param data                原始数据
     * @param primaryKeyColumns   主键列（用于重新排序，可选）
     * @param duplicateCheckColumns 查重列（用于判断重复，必填）
     * @return 去重并重新排序后的数据
     */
    public List<Map<String, Object>> removeDuplicates(
            List<Map<String, Object>> data,
            List<String> primaryKeyColumns,
            List<String> duplicateCheckColumns) {

        if (data == null || data.isEmpty()) {
            return Collections.emptyList();
        }

        if (duplicateCheckColumns == null || duplicateCheckColumns.isEmpty()) {
            throw new IllegalArgumentException("查重列不能为空");
        }

        // 1. 去重处理
        Set<String> uniqueKeys = new LinkedHashSet<>(); // 保持插入顺序
        List<Map<String, Object>> deduplicatedData = new ArrayList<>();

        for (Map<String, Object> row : data) {
            // 生成查重键
            String checkKey = generateCheckKey(row, duplicateCheckColumns);

            // 如果是首次出现，添加到结果集
            if (!uniqueKeys.contains(checkKey)) {
                uniqueKeys.add(checkKey);
                deduplicatedData.add(new LinkedHashMap<>(row)); // 创建副本
            }
        }

        // 2. 重新排序主键ID（如果有主键列）
        if (primaryKeyColumns != null && !primaryKeyColumns.isEmpty()) {
            return reorderPrimaryKeys(deduplicatedData, primaryKeyColumns);
        }

        return deduplicatedData;
    }

    /**
     * 重新排序主键ID
     */
    private List<Map<String, Object>> reorderPrimaryKeys(
            List<Map<String, Object>> data,
            List<String> primaryKeyColumns) {

        // 只处理第一个主键列（通常是ID）
        String primaryKey = primaryKeyColumns.get(0);
        int nextId = 1;  // 直接从1开始计数

        // 重新分配ID（忽略原有ID值）
        for (Map<String, Object> row : data) {
            row.put(primaryKey, nextId++);
        }

        return data;
    }

    /**
     * 生成查重键（基于指定的查重列）
     */
    private String generateCheckKey(Map<String, Object> row, List<String> columns) {
        StringBuilder key = new StringBuilder();
        for (String column : columns) {
            Object value = row.get(column);
            if (value != null) {
                // 使用固定格式确保值一致性
                key.append("{").append(column).append(":").append(value.toString()).append("}");
            } else {
                key.append("{").append(column).append(":NULL}");
            }
        }
        return key.toString();
    }

    /**
     * 按行顺序填充连续自增ID（确保ID连续无间隔）
     */
    private List<Map<String, Object>> fillSequentialId(List<Map<String, Object>> data) {
        if (data == null || data.isEmpty()) {
            return data;
        }

        // 记录上一行的有效ID值
        int lastValidId = 0;
        // 记录已使用的ID值，避免冲突
        Set<Integer> usedIds = new HashSet<>();

        // 第一遍：收集所有已使用的ID
        for (Map<String, Object> row : data) {
            Object idObj = row.get("id");
            if (idObj != null) {
                try {
                    int id = parseId(idObj);
                    usedIds.add(id);
                } catch (NumberFormatException e) {
                    // 非数字ID忽略
                }
            }
        }

        // 第二遍：按行顺序填充缺失ID
        for (Map<String, Object> row : data) {
            Object idObj = row.get("id");

            // 处理非空ID
            if (idObj != null) {
                try {
                    int currentId = parseId(idObj);

                    // 更新最后有效ID（取较大值）
                    if (currentId > lastValidId) {
                        lastValidId = currentId;
                    }
                    continue; // 已有ID，跳过填充
                } catch (NumberFormatException e) {
                    // 非数字ID视为缺失，继续填充流程
                }
            }

            // 查找可用的最小ID（从lastValidId+1开始）
            int newId = lastValidId + 1;
            while (usedIds.contains(newId)) {
                newId++;
            }

            // 填充新ID并更新状态
            row.put("id", newId);
            usedIds.add(newId);
            lastValidId = newId;
        }

        return data;
    }

    /**
     * 解析ID值（支持整数和字符串形式）
     */
    private int parseId(Object idObj) throws NumberFormatException {
        if (idObj instanceof Number) {
            return ((Number) idObj).intValue();
        } else if (idObj instanceof String) {
            return Integer.parseInt((String) idObj);
        }
        throw new NumberFormatException("无法解析ID值: " + idObj);
    }

    // 私有工具方法：创建算法配置文件
    private Path createTempConfigFile(String targetColumn, List<String> dependentColumns, List<Map<String, Object>> data) throws IOException {
        Path tempFile = Files.createTempFile("missing_value_config", ".txt");

        // 获取列索引
        Map<String, Object> firstRow = data.get(0);
        List<String> headers = new ArrayList<>(firstRow.keySet());
        int targetIndex = headers.indexOf(targetColumn);

        // 构建配置文件内容
        StringBuilder configBuilder = new StringBuilder();
        configBuilder.append(targetIndex).append("#");

        // 添加依赖列索引
        for (int i = 0; i < dependentColumns.size(); i++) {
            configBuilder.append(headers.indexOf(dependentColumns.get(i)));
            if (i < dependentColumns.size() - 1) {
                configBuilder.append(",");
            }
        }
        configBuilder.append("\n");

        // 添加可能的填充值（从数据中提取非空值）
        Set<Object> possibleValues = new HashSet<>();
        for (Map<String, Object> row : data) {
            Object value = row.get(targetColumn);
            if (value != null) {
                possibleValues.add(value.toString());
            }
        }

        for (Object value : possibleValues) {
            configBuilder.append(value).append("\n");
        }

        Files.write(tempFile, configBuilder.toString().getBytes(), StandardOpenOption.WRITE);
        return tempFile;
    }

    // 私有工具方法：格式化数据为算法可处理的格式
    private List<String> formatDataForAlgorithm(List<Map<String, Object>> data) {
        List<String> formattedData = new ArrayList<>();

        // 添加表头行
        if (!data.isEmpty()) {
            Map<String, Object> firstRow = data.get(0);
            StringBuilder header = new StringBuilder("0\t");
            for (String key : firstRow.keySet()) {
                header.append(key).append("|");
            }
            if (header.length() > 0) {
                header.deleteCharAt(header.length() - 1); // 删除最后一个|
            }
            formattedData.add(header.toString());
        }

        // 添加数据行（将null转换为?表示缺失值）
        for (int i = 0; i < data.size(); i++) {
            Map<String, Object> row = data.get(i);
            StringBuilder line = new StringBuilder((i + 1) + "\t");

            for (Object value : row.values()) {
                line.append(value == null ? "?" : value.toString()).append("|");
            }

            if (line.length() > 0) {
                line.deleteCharAt(line.length() - 1); // 删除最后一个|
            }

            formattedData.add(line.toString());
        }

        return formattedData;
    }

    // 私有工具方法：解析算法输出结果
    private List<Map<String, Object>> parseFormattedData(List<String> formattedData) {
        List<Map<String, Object>> result = new ArrayList<>();

        if (formattedData.isEmpty()) {
            return result;
        }

        // 解析表头
        String[] headerParts = formattedData.get(0).split("\t");
        if (headerParts.length < 2) {
            return result;
        }
        String[] headers = headerParts[1].split("\\|");

        // 解析数据行（将?转回null）
        for (int i = 1; i < formattedData.size(); i++) {
            String[] lineParts = formattedData.get(i).split("\t");
            if (lineParts.length < 2) {
                continue;
            }

            String[] values = lineParts[1].split("\\|");
            Map<String, Object> row = new LinkedHashMap<>();

            for (int j = 0; j < Math.min(headers.length, values.length); j++) {
                row.put(headers[j], "?".equals(values[j]) ? null : values[j]);
            }

            result.add(row);
        }
        return result;
    }
}